package com.example.lotterysystem.dao.handler;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.example.lotterysystem.dao.dataobject.Encrypt;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Created with IntelliJ IDEA.
 * Description: 手机号的数据处理(手机号存储前的加密)
 * BaseTypeHandler<Encrypt> 父类
 * User: Spider-Man
 * Date: 2025-09-07
 * Time: 20:57
 */
@MappedTypes(Encrypt.class) //被处理的类型.
@MappedJdbcTypes(JdbcType.VARCHAR) //转换后的类型.
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt>{

    //生成秘钥
     private final byte[] KEY = "123456789abcdefg".getBytes(StandardCharsets.UTF_8);

    /**
     * 设置参数
     * @param preparedStatement SQL预编译对象
     * @param i 需要赋值的索引位置
     * @param encrypt 原本i位置需要赋值的对象
     * @param jdbcType jdbc类型
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Encrypt encrypt, JdbcType jdbcType) throws SQLException {
        //预编译对象为空 或者 对象当中的值为空, 此时需要向i位置放一个null
        if(encrypt == null || encrypt.getValue() == null) {
            preparedStatement.setString(i,null);
            return;
        }
        System.out.println("加密的内容: " + encrypt.getValue());
        //值不为空,先进行加密.
        AES aes = SecureUtil.aes(KEY); // 对密钥创建一个AES对象
        String encrypet = aes.encryptHex(encrypt.getValue());//针对电话号码进行加密
        //对加密结果进行存储
        preparedStatement.setString(i,encrypet);
    }

    /**
     * 获取值 (解密)
     * @param resultSet  结果集合
     * @param s 索引名
     * @return
     * @throws SQLException
     */
    @Override
    public Encrypt getNullableResult(ResultSet resultSet, String s) throws SQLException {
        System.out.println("获取值得到的加密内容: " + resultSet.getString(s));
        return decrypt(resultSet.getString(s));
    }

    /**
     * 获取值
     * @param resultSet 结果集合
     * @param i 索引位置
     * @return
     * @throws SQLException
     */
    @Override
    public Encrypt getNullableResult(ResultSet resultSet, int i) throws SQLException {
        System.out.println("获取值得到的加密内容: " + resultSet.getString(i));
        return decrypt(resultSet.getString(i));
    }

    /**
     * 获取值
     * @param callableStatement 结果集合
     * @param i 索引
     * @return 存放过程使用的
     * @throws SQLException
     */
    @Override
    public Encrypt getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        System.out.println("获取值得到的内容: " + callableStatement.getString(i));
        return decrypt(callableStatement.getString(i));
    }

    //解密方法
    private Encrypt decrypt(String str) {
        //是一个空的,直接进行返回,不需要进行解密
        if(str == null) {
            return null;
        }
        //解密
        return new Encrypt(SecureUtil.aes(KEY).decryptStr(str));
    }

}
